package com.ucpaas.monitor.util;
import java.io.IOException;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryManagerMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import java.lang.management.MonitorInfo;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.management.MBeanServerConnection;

import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;  
  
/** 
 * 系统监控工具 
 * management 和底层虚拟机的关系是非常紧密的。其实，有一些的是直接依靠虚拟机提供的公 
 * 开 API 实现的，比如 JVMTI；而另外一些则不然，很大一块都是由虚拟机底层提供某些不公开 
 * 的 API / Native Code 提供的。这样的设计方式，保证了 management 包可以提供足够的信 
 * 息，并且使这些信息的提供又有足够的效率；也使 management 包和底层的联系非常紧密。 
 * @author longgangbai 
 *  
 */  
public class SystemUtils {  
	public static final Logger logger = LoggerFactory.getLogger(SystemUtils.class);
	
    /** 
     *  
     * @return 
     */  
    public static final String getHeapMemoryUsage() {  
        return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()  
                .getUsed()  
                + "/"  
                + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()  
                        .getMax();  
    }  
    /** 
     * 当前使用内存的百分比 
     * @return 
     */  
    public static final String getHeapMemoryUsagePercent() {  
        return (((double) ManagementFactory.getMemoryMXBean()  
                .getHeapMemoryUsage().getUsed() / (double) ManagementFactory  
                .getMemoryMXBean().getHeapMemoryUsage().getMax()) * 100L)  
                + "%";  
    }  
    /** 
     * 当前非java堆占用的百分比 
     * @return 
     */  
    public static final String getNonHeapMemoryUsage() {  
        return ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()  
                .getUsed()  
                + "/"  
                + ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()  
                        .getMax();  
    }  
      /** 
     *  
     * @return 
     */  
    public static final String getNonHeapMemoryUsagePercent() {  
        return (((double) ManagementFactory.getMemoryMXBean()  
                .getNonHeapMemoryUsage().getUsed() / (double) ManagementFactory  
                .getMemoryMXBean().getNonHeapMemoryUsage().getMax()) * 100)  
                + "%";  
    }  
      /** 
     * 获取线程数 
     * @return 
     */  
    public static final String getThreadCount() {  
        return "" + ManagementFactory.getThreadMXBean().getThreadCount();  
    }
    
    public static void printMemPoolMx(MBeanServerConnection mbs) throws IOException {
		List<MemoryPoolMXBean> memoryPoolMXBeanList =  
    			ManagementFactory.getPlatformMXBeans(mbs, MemoryPoolMXBean.class);
        
        //该信息提供了大量的信息。在 JVM 中，可能有几个内存池，因此有对应的内存池信息，因此，在工厂类中  
        //，getMemoryPoolMXBean() 得到是一个 MemoryPoolMXBean 的 list。每一个 MemoryPoolMXBean 都包含  
        //了该内存池的详细信息，如是否可用、当前已使用内存 / 最大使用内存值、以及设置最大内存值等等。  
        for (MemoryPoolMXBean memoryPoolMXBean : memoryPoolMXBeanList) {  
            //内存池的名称  
            String poolName=memoryPoolMXBean.getName();  
            logger.info("内存池名称："+poolName);  
            //内存管理器的名称  
            String[] memoryMgrNames=memoryPoolMXBean.getMemoryManagerNames();  
            for (String mgrName : memoryMgrNames) {  
                logger.info("内存管理器的名称："+mgrName);  
            }  
            //java JVM最近内存的使用情况  
            MemoryUsage memoryUsage=memoryPoolMXBean.getCollectionUsage();  
            logger.info("内存池的收集器内存使用率："+memoryUsage.getUsed()/memoryUsage.getMax()+"%");  
            logger.info("返回此内存池的集合使用阈值（字节）:{},默认值为零。集合使用阈值可以通过setCollectionUsageThreshold方法更改",memoryPoolMXBean.getCollectionUsageThreshold());
            logger.info("返回Java虚拟机已检测到内存使用量已达到或超过集合使用阈值的次数:" +  memoryPoolMXBean.getCollectionUsageThresholdCount());
            MemoryType  memoryType=memoryPoolMXBean.getType();  
            logger.info("内存的信息："+memoryType.name());  
            MemoryUsage memoryUage=memoryPoolMXBean.getUsage();  
            logger.info("内存池的内存使用率："+memoryUage.getUsed()/memoryUage.getMax()+"%");  
            long usageThreshold = memoryPoolMXBean.getUsageThreshold();  
            logger.info("返回此内存池的使用阈值（字节）:{}每个内存池都有一个与平台相关的默认阈值。可以通过setusagethreshold方法更改当前使用阈值",usageThreshold);
            logger.info("返回内存使用量超过使用阈值的次数:"+memoryPoolMXBean.getUsageThresholdCount());
        }
	}

	public static void printMemoryMgrMx(MBeanServerConnection mbs) throws IOException {
		//提供了内存管理类和内存池（memory pool）的名字信息。  
        List<MemoryManagerMXBean> memoryMgrMXBeanList =  
    			ManagementFactory.getPlatformMXBeans(mbs, MemoryManagerMXBean.class);
        //内存管理器的信息  
        for (MemoryManagerMXBean memoryManagerMXBean : memoryMgrMXBeanList) {  
            String[] poolNames=memoryManagerMXBean.getMemoryPoolNames();  
            for (String poolName : poolNames) {  
                logger.info("poolNames="+poolName);  
            }  
        }
	}

	public static void printGcMx(MBeanServerConnection mbs) throws IOException {
		List<GarbageCollectorMXBean> gcMXBeanList = 
        			ManagementFactory.getPlatformMXBeans(mbs, GarbageCollectorMXBean.class);
        //相对于开放人员对 GC 的关注程度来说，该 mxbean 提供的信息十分有限，仅仅提供了 GC 的次数和 GC 花费总时间的近似值。  
        for (GarbageCollectorMXBean gcMXBean : gcMXBeanList) {  
            //内存池名称  
            String[] poolNames=gcMXBean.getMemoryPoolNames();  
            for (String poolName : poolNames) {  
                logger.info("poolNames="+poolName);  
            }  
        }
	}

	public static void printCompileMx(MBeanServerConnection mbs) throws IOException {
		//CompilationMXBean 帮助用户了解当前的编译器和编译情况，该 mxbean 提供的信息不多。  
        CompilationMXBean compilationMXBean = ManagementFactory.newPlatformMXBeanProxy(mbs,
				ManagementFactory.COMPILATION_MXBEAN_NAME, 
				CompilationMXBean.class);  
        String jitName=compilationMXBean.getName();  
        logger.info("即时编译的名称："+jitName);  
        long totalCompileTime=compilationMXBean.getTotalCompilationTime();  
        logger.info("总的编译时间："+totalCompileTime+"/s");  
        boolean isSupport=compilationMXBean.isCompilationTimeMonitoringSupported();  
        if(isSupport){  
            logger.info("支持即时编译器编译监控");  
        }else{  
            logger.info("不支持即时编译器编译监控");  
        }
	}

	public static void printClassLoadMx(MBeanServerConnection mbs) throws IOException {
		ClassLoadingMXBean classLoadMXBean = ManagementFactory.newPlatformMXBeanProxy(mbs,
													ManagementFactory.CLASS_LOADING_MXBEAN_NAME, 
													ClassLoadingMXBean.class);  
        int loadClazzCount=classLoadMXBean.getLoadedClassCount();  
        logger.info("加载类的数量："+loadClazzCount);  
          
        long hasloadClazzCount=classLoadMXBean.getTotalLoadedClassCount();  
        logger.info("已经加载类的数量："+hasloadClazzCount);  
        long hasUnloadClazzCount=classLoadMXBean.getUnloadedClassCount();  
        logger.info("尚未加载类的数量："+hasUnloadClazzCount);  
        boolean isVerbose=classLoadMXBean.isVerbose();  
        logger.info("是否开始加载类信息："+isVerbose);
	}

	public static void printThreadMx(MBeanServerConnection mbs) throws IOException {
		ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy(mbs,
														ManagementFactory.THREAD_MXBEAN_NAME, 
														ThreadMXBean.class);  
        //在 Java 这个多线程的系统中，对线程的监控是相当重要的。ThreadMXBean 就是起到这个作用。  
        //ThreadMXBean 可以提供的信息包括各个线程的各种状态，CPU 占用情况，以及整个系统中的线  
        //程状况。从 ThreadMXBean 可以得到某一个线程的 ThreadInfo 对象。这个对象中则包含了这个  
        //线程的所有信息。  
        //线程的信息  
        //所有的线程的编号  
        long[] threadIds=threadMXBean.getAllThreadIds();  
        for (long threadId : threadIds) {  
            //线程的信息  
            ThreadInfo  threadInfo=threadMXBean.getThreadInfo(threadId);  
            //线程被阻塞的数量  
            threadInfo.getBlockedCount();  
            //被锁定线程的监控信息  
            MonitorInfo[] monitorInfos=threadInfo.getLockedMonitors();  
            for (MonitorInfo monitorInfo : monitorInfos) {  
                int depth=monitorInfo.getLockedStackDepth();  
                logger.info("锁定的程度："+depth);  
            }  
            //异步锁定的信息  
            LockInfo[] lockinfos=threadInfo.getLockedSynchronizers();  
            //锁定的信息  
            for (LockInfo lockInfo : lockinfos) {  
                logger.info("锁定类的名称："+lockInfo.getClassName());  
            }  
            //线程的名称  
            String threadName=threadInfo.getThreadName();  
            logger.info("线程的名称："+threadName);  
            Thread.State state=threadInfo.getThreadState();  
            logger.info("线程的信息："+state.name());  
              
        }  
          
        long cpuTime=threadMXBean.getCurrentThreadCpuTime();  
        logger.info("返回当前线程的总CPU时间（纳秒）:"+cpuTime);
        long curentTime=threadMXBean.getCurrentThreadUserTime();  
        logger.info("返回当前线程在用户模式下以纳秒为单位执行的CPU时间:（纳秒）"+curentTime);
        long threadCount=threadMXBean.getDaemonThreadCount();  
        logger.info("返回当前活动的守护进程线程数:" + threadCount);
        long peakliveThreadCount=threadMXBean.getPeakThreadCount();  
        logger.info("返回Java虚拟机启动或峰值重置后的峰值实况线程计数:"+peakliveThreadCount);
        long threadCounts=threadMXBean.getThreadCount();  
        logger.info("当前处于live状态的线程总的数量："+threadCounts);  
        long totalThreadCount=threadMXBean.getTotalStartedThreadCount();  
        logger.info("JVM 启动之后，总的自动线程数量："+totalThreadCount);
	}

	public static void printRuntimeMxBean(MBeanServerConnection mbs) throws IOException {
		RuntimeMXBean runtimeMXBean = ManagementFactory.newPlatformMXBeanProxy(mbs,
														ManagementFactory.RUNTIME_MXBEAN_NAME, 
														RuntimeMXBean.class);  
        String vmName=runtimeMXBean.getVmName();  
        logger.info("虚拟机的名称："+vmName);  
          
        String vmVersion=runtimeMXBean.getVmVersion();  
        logger.info("虚拟机的版本："+vmVersion);  
          
        Map<String, String> sysMaps=runtimeMXBean.getSystemProperties();  
        Set<Entry<String,String>> keyLists=sysMaps.entrySet();  
        for (Entry<String, String> entry : keyLists) {  
            logger.info(entry.getKey()+":"+entry.getValue());  
        }  
        String vmVendor=runtimeMXBean.getVmVendor();  
        logger.info("系统的供应商的名称："+vmVendor);  
          
        //类加载器的路径  
        String clazzPath=runtimeMXBean.getClassPath();//System.getProperty("java.class.path")}  
        logger.info("操作系统的类加载器的名称："+clazzPath);  
          
        List<String> argsList=runtimeMXBean.getInputArguments();  
        logger.info("操作系统的参数信息");  
        for (String args : argsList) {  
            logger.info("  "+args);  
        }  
          
        String libPath=runtimeMXBean.getLibraryPath();// System.getProperty("java.library.path")  
        logger.info("java 的类库路径："+libPath );  
          
        String specVersion=runtimeMXBean.getManagementSpecVersion();  
        logger.info("实施运行Java虚拟机管理接口规范 的版本"+specVersion);  
          
        String specName=runtimeMXBean.getSpecName();  
        logger.info("规范的名称："+specName);  
          
        String specVender=runtimeMXBean.getSpecVendor();  
        logger.info("规范管理接口供应商 ："+specVender);  
          
        long startTime=runtimeMXBean.getStartTime();  
        logger.info("java　虚拟机的开始启动的时间："+startTime);  
          
  
        runtimeMXBean.getSpecVersion();  
          
        String bottClassPath =runtimeMXBean.getBootClassPath();  
        logger.info("操作系统的bootstrap 的classloader："+bottClassPath);
	}

	public static void printOperatorSysMx(MBeanServerConnection mbs) throws IOException {
		//获取远程opretingsystemmxbean  
		OperatingSystemMXBean operateSystemMBean = ManagementFactory.newPlatformMXBeanProxy(mbs,
																	ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, 
																	OperatingSystemMXBean.class);  
		 String operateName=operateSystemMBean.getName();  
        logger.info("操作系统的名称："+operateName);  
          
        int processListCount=operateSystemMBean.getAvailableProcessors();  
        logger.info("操作系统的进程数："+processListCount);  
          
        String osArchName=operateSystemMBean.getArch();//System.getProperty("os.arch");  
        logger.info("操作系统的架构："+osArchName);  
          
        double loadAverage=operateSystemMBean.getSystemLoadAverage();  
        logger.info("操作系统的负载均衡信息："+loadAverage);  
          
        String versionName=operateSystemMBean.getVersion();//System.getProperty("os.version");  
        logger.info("操作系统的版本号码："+versionName);
	}

	public static void printMemoryMx(MBeanServerConnection mbs) throws IOException {
		//获取远程memorymxbean  
		MemoryMXBean memoryMXBean=ManagementFactory.newPlatformMXBeanProxy(mbs,
												ManagementFactory.MEMORY_MXBEAN_NAME, 
												MemoryMXBean.class);  
		
        //java堆得使用情况信息  
        MemoryUsage heapMemoryUsage=memoryMXBean.getHeapMemoryUsage();  
        long usaged=heapMemoryUsage.getUsed();  
        logger.info("java 内存堆使用内存："+usaged);  
        long maxUsage=heapMemoryUsage.getMax();  
        logger.info("java 内存堆最大使用内存："+maxUsage);  
        long initUsage=heapMemoryUsage.getInit();  
        logger.info("java 内存堆初始化时占用内存："+initUsage);
	}
	
  
}  